package jenetics.test;

import java.util.stream.IntStream;

import org.jenetics.Chromosome;
import org.jenetics.EnumGene;
import org.jenetics.Genotype;
import org.jenetics.Optimize;
import org.jenetics.PartiallyMatchedCrossover;
import org.jenetics.PermutationChromosome;
import org.jenetics.SwapMutator;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.engine.EvolutionStatistics;
import org.jenetics.engine.limit;
import org.jenetics.stat.DoubleMomentStatistics;
import org.jenetics.util.LCG64ShiftRandom;
import org.jenetics.util.RandomRegistry;

public class Sorting {

	public static void main(String[] args) {
		RandomRegistry.setRandom(new LCG64ShiftRandom.ThreadLocal());
		final Engine<EnumGene<Integer>, Integer> engine = 
				Engine.builder(Sorting::length, PermutationChromosome.ofInteger(20)).optimize(Optimize.MINIMUM).populationSize(1000).offspringFraction(0.9)
				.alterers(new SwapMutator<>(0.01), new PartiallyMatchedCrossover<>(0.3)).build();
		
		final EvolutionStatistics<Integer, DoubleMomentStatistics> statistics = EvolutionStatistics.ofNumber();
		
		final EvolutionResult<EnumGene<Integer>, Integer> result = engine.stream().limit(limit.bySteadyFitness(100)).limit(2500).peek(statistics).collect(EvolutionResult.toBestEvolutionResult());
		
		System.out.println(statistics);
		System.out.println(result.getBestPhenotype());
	}
	
	private static int length(final Genotype<EnumGene<Integer>> genotype) {
		return IntStream.range(1, genotype.getChromosome().length()).map(i -> dist(genotype.getChromosome(), i, i - 1)).sum();
	}

	private static int dist(Chromosome<EnumGene<Integer>> path, int i, int j) {
		return (path.getGene(i).getAllele() - path.getGene(j).getAllele()) * (path.getGene(i).getAllele() - path.getGene(j).getAllele());
	}

}